package com.dubbo.framework.config;

import cn.hutool.core.convert.Convert;
import cn.hutool.setting.dialect.Props;
import com.dubbo.framework.URL;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

import java.util.ArrayList;
import java.util.List;

import static com.dubbo.framework.consts.DubboConstant.*;

/**
 * 服务启动时，将服务注册到注册中心中
 *
 * @author by Mr. Li 2021/4/29 14:23
 */
@Slf4j
public class ServerConfig {

    public static CuratorFramework CLIENT;
    public static String SERVER_NAME_PREFIX;

    // 读取远程注册中心的服务
    static {
        // 读取配置类
        Props props = new Props("zookeeper.properties");
        final Props props1 = new Props("application.properties");
        SERVER_NAME_PREFIX = Convert.toStr(props1.get(ZK_SERVER_NAME_PREFIX));
        final String zkAddr = (String) props.get(ZK_ADDR);
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);

        CLIENT = CuratorFrameworkFactory.builder()
                .connectString(zkAddr)
                .sessionTimeoutMs(Convert.toInt(props.get(ZK_SESSION_TIMEOUT_MS)))
                .connectionTimeoutMs(Convert.toInt(props.get(ZK_CONNECTION_TIMEOUT_MS)))
                .namespace(Convert.toStr(props1.get(ZK_ADDR_NAMESPACE))) //命名空间。
                .retryPolicy(retryPolicy)
                .build();  // 建立连接通道。
        CLIENT.start();
    }

    /**
     * 上线服务 到zk中
     *
     * @param url 访问地址
     */
    public static void up(URL url) {

        try {
            final Stat stat = CLIENT.checkExists().forPath("/" + SERVER_NAME_PREFIX);
            if (stat == null) {
                CLIENT.create().withMode(CreateMode.PERSISTENT).forPath("/" + SERVER_NAME_PREFIX);
            }

            CLIENT.create().withMode(CreateMode.EPHEMERAL).forPath("/" + SERVER_NAME_PREFIX + "/" + url.toString());
            log.info("{}上线成功>>>>>>>>>>>", url);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 拉取 注册中心的服务信息
     *
     * @return List<URL>
     */
    public static List<URL> pull() {
        //final Props props1 = new Props("application.properties");
        List<URL> addrs = new ArrayList<>();
        try {
            //final byte[] bytes = client.getData().forPath("/" + Convert.toStr(props1.get(ZK_ADDR_NAMESPACE)));
            //client.getChildren()
            final List<String> strings = CLIENT.getChildren().forPath("/" + SERVER_NAME_PREFIX); // 基于namespace的 client 调用的所有命令中都会带上namespace前缀
            assert strings.size() != 0;
            strings.forEach(s -> {
                final String[] split = s.split(",");
                final URL url = new URL();
                url.setIpAddr(split[0]);
                url.setPort(Convert.toInt(split[1]));
                addrs.add(url);
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
        return addrs;
    }

}
